package cn.nexd.location.indoor.core;

import android.content.Context;
import android.util.Log;

import java.io.IOException;
import java.util.List;

import cn.nexd.location.indoor.NexdIndoorLocation;
import cn.nexd.location.indoor.NexdIndoorLocationConfiguration;
import cn.nexd.location.indoor.NexdIndoorLocationResult;
import cn.nexd.location.indoor.bean.IndoorLocationData;
import cn.nexd.location.indoor.core.mathematician.IndoorLocation;
import cn.nexd.location.indoor.core.mathematician.LocationEngineResult;
import cn.nexd.location.indoor.listener.NexdIndoorLocationListener;
import cn.nexd.location.indoor.thread.TaskExecutor;

/**
 * Created by codngfish on 16/5/24.
 */
public class IndoorLocationThread {


    private final IndoorLocation indoorLocation;
    private boolean interrupt = false;
    private Context context;

    public IndoorLocationThread(Context context) {
        this.context = context;
        indoorLocation = new IndoorLocation();
    }

    public boolean getCurrentIndoorLocationThreadState() {
        return interrupt;
    }

    public void start(long buildingId, long floorId, boolean focusOnline, List<IndoorLocationData> indoorLocationDatas, NexdIndoorLocationListener locationListener, NexdIndoorLocationConfiguration indoorLocationConfiguration) {

        if (interrupt) {
            return;
        }

        if (focusOnline) {
            //强制在线定位
            return;
        }

        if (buildingId == -1L) {
            if (floorId == -1L) {
                // 模糊定位,在线支持
                //暂不支持
                Log.e("location", "buildingId 不能为-1");
                return;
            }
        } else {
            if (floorId == -1L) {
                // 切层与定位
                //                ThreadPoolManager.getThreadPoolManagerInstance().addTaskExecutorService(new DefaultIndoorLocationDetectionThread(indoorLocationDatas, buildingId, locationListener));
                //                TaskExecutor.newCyclicBarrierExecutor().put(new DefaultDetectionConfigThread(buildingId, locationListener)).start(new DefaultIndoorLocationDetectionThread(indoorLocationDatas, buildingId, locationListener));
                TaskExecutor.startAllowingLoss(new DefaultIndoorLocationDetectionThread(indoorLocationDatas, buildingId, locationListener));
            } else {
                // 只定位,不需要切层
                //                                ThreadPoolManager.getThreadPoolManagerInstance().addTaskExecutorService(new DefaultIndoorLocationThread(indoorLocationDatas, buildingId, floorId, locationListener));
                //                TaskExecutor.newCyclicBarrierExecutor().put(new DefaultLocationConfigThread(buildingId, floorId, locationListener)).start(new DefaultIndoorLocationThread(indoorLocationDatas, buildingId, floorId, locationListener));
                TaskExecutor.startAllowingLoss(new DefaultIndoorLocationThread(indoorLocationDatas, buildingId, floorId, locationListener));
            }
        }
    }

    // 定位,切层与定位
    private class DefaultIndoorLocationDetectionThread implements Runnable {
        private List<IndoorLocationData> indoorLocationDatas;
        private long buildingId;
        private NexdIndoorLocationListener locationListener;

        public DefaultIndoorLocationDetectionThread(List<IndoorLocationData> indoorLocationDatas, long buildingId, NexdIndoorLocationListener locationListener) {
            this.indoorLocationDatas = indoorLocationDatas;
            this.buildingId = buildingId;
            this.locationListener = locationListener;
        }

        @Override
        public void run() {

            // 判断 是否存在切层配置文件,先切层,然后定位
            if (indoorLocation.getCurrentBuildingId() == -1L || indoorLocation.getCurrentBuildingId() != buildingId) {
                //                Log.d("location_test", "需要加载切层文件");
                try {
                    indoorLocation.initDetectionConfig(NexdIndoorLocation.getConfigurationPath(context, buildingId).toString() + buildingId + ".CONF", NexdIndoorLocation.getConfigurationPath(context, buildingId).toString() + buildingId + ".model", NexdIndoorLocation.getConfigurationPath(context, buildingId).toString() + buildingId + ".wifilist");
                    indoorLocation.setCurrentBuildingId(buildingId);
                } catch (IOException e) {
                    locationListener.onLocationInterrupt(NexdIndoorLocation.LocationState.LOCATION_INTERRUP_LOCATION_CONFIG_NONEXISTENT);
                    indoorLocation.setCurrentBuildingId(-1L);
                    Log.e("", e.getMessage());
                }
            }

            final long floorId = indoorLocation.locationDetection(indoorLocationDatas);
            //            Log.d("location_test", "正在定位,定位与切层 , 计算出来的 floorID == " + floorId);
            //            TaskExecutor.newCyclicBarrierExecutor().put(new DefaultLocationConfigThread(buildingId, floorId, locationListener)).start(new DefaultIndoorLocationThread(indoorLocationDatas, buildingId, floorId, locationListener));
            // 判断是否存在定位文件
            if (indoorLocation.getCurrentFloorId() == -1L || indoorLocation.getCurrentFloorId() != floorId) {
                // 配置文件不对,加载
                //                Log.d("location_test", "需要加载定位文件,当前已经存在的定位配置 " + indoorLocation.getCurrentFloorId());
                try {
                    indoorLocation.initLocationConfig(NexdIndoorLocation.getConfigurationPath(context, buildingId) + Long.toString(floorId) + ".optparam", NexdIndoorLocation.getConfigurationPath(context, buildingId) + Long.toString(floorId) + ".wp", NexdIndoorLocation.getConfigurationPath(context, buildingId) + Long.toString(floorId) + ".wifilist");
                    indoorLocation.setCurrentFloorId(floorId);
                } catch (IOException e) {
                    locationListener.onLocationInterrupt(NexdIndoorLocation.LocationState.LOCATION_INTERRUP_LOCATION_CONFIG_NONEXISTENT);
                    indoorLocation.setCurrentFloorId(-1L);
                    interrupt = true;
                    Log.e("", e.getMessage());
                }
            }

            // 定位

            LocationEngineResult locationEngineResult = indoorLocation.locationIndoorPosition(indoorLocationDatas, buildingId, floorId);

            if (Float.compare(locationEngineResult.getX(), -1F) == 0 || Float.compare(locationEngineResult.getY(), -1F) == 0) {
                // 定位失败
                locationListener.onLocationFailed(NexdIndoorLocation.LocationState.LOCATION_FAILED_COLLECTOR_CONFIG_UNCONSISTENT);
            } else {
                locationListener.onLocationSuccess(new NexdIndoorLocationResult(locationEngineResult));
            }
        }
    }

    // 定位,只定位,此时 buildingID 与 floorID 是明确的
    private class DefaultIndoorLocationThread implements Runnable {
        private List<IndoorLocationData> indoorLocationDatas;
        private long buildingId;
        private long floorId;
        private NexdIndoorLocationListener locationListener;

        public DefaultIndoorLocationThread(List<IndoorLocationData> indoorLocationDatas, long buildingId, long floorId, NexdIndoorLocationListener locationListener) {
            this.indoorLocationDatas = indoorLocationDatas;
            this.buildingId = buildingId;
            this.floorId = floorId;
            this.locationListener = locationListener;
        }


        @Override
        public void run() {
            // 判断是否存在定位配置文件

            if (indoorLocation.getCurrentFloorId() == -1L || indoorLocation.getCurrentFloorId() != floorId) {
                // 配置文件不对,加载
                //                Log.d("location_test", "需要加载定位文件,当前已经存在的定位配置 " + indoorLocation.getCurrentFloorId());
                try {
                    indoorLocation.initLocationConfig(NexdIndoorLocation.getConfigurationPath(context, buildingId) + Long.toString(floorId) + ".optparam", NexdIndoorLocation.getConfigurationPath(context, buildingId) + Long.toString(floorId) + ".wp", NexdIndoorLocation.getConfigurationPath(context, buildingId) + Long.toString(floorId) + ".wifilist");
                    indoorLocation.setCurrentFloorId(floorId);
                } catch (IOException e) {
                    locationListener.onLocationInterrupt(NexdIndoorLocation.LocationState.LOCATION_INTERRUP_LOCATION_CONFIG_NONEXISTENT);
                    indoorLocation.setCurrentFloorId(-1L);
                    interrupt = true;
                    Log.e("", e.getMessage());
                }
            }


            LocationEngineResult locationEngineResult = indoorLocation.locationIndoorPosition(indoorLocationDatas, buildingId, floorId);
            if (Float.compare(locationEngineResult.getX(), -1F) == 0 || Float.compare(locationEngineResult.getY(), -1F) == 0) {
                // 定位失败
                locationListener.onLocationFailed(NexdIndoorLocation.LocationState.LOCATION_FAILED_COLLECTOR_CONFIG_UNCONSISTENT);
            } else {
                locationListener.onLocationSuccess(new NexdIndoorLocationResult(locationEngineResult));
            }
            //            Log.d("location_test", "正在定位,只定位,不切层");
        }
    }

    //    // 检查 加载 定位配置文件
    //    private class DefaultLocationConfigThread extends SimpleTask {
    //        private long buildingId;
    //        private long floorId;
    //        private NexdIndoorLocationListener indoorLocationListener;
    //
    //        public DefaultLocationConfigThread(long buildingId, long floorId, NexdIndoorLocationListener indoorLocationListener) {
    //            this.buildingId = buildingId;
    //            this.floorId = floorId;
    //            this.indoorLocationListener = indoorLocationListener;
    //        }
    //
    //
    //        @Override
    //        protected Object doInBackground() {
    //            if (indoorLocation.getCurrentFloorId() == -1L || indoorLocation.getCurrentFloorId() != floorId) {
    //                // 配置文件不对,加载
    //                //                Log.d("location_test", "需要加载定位文件,当前已经存在的定位配置 " + indoorLocation.getCurrentFloorId());
    //                try {
    //                    indoorLocation.initLocationConfig(NexdIndoorLocation.getConfigurationPath(buildingId) + Long.toString(floorId) + ".optparam", NexdIndoorLocation.getConfigurationPath(buildingId) + Long.toString(floorId) + ".wp", NexdIndoorLocation.getConfigurationPath(buildingId) + Long.toString(floorId) + ".wifilist");
    //                    indoorLocation.setCurrentFloorId(floorId);
    //                } catch (IOException e) {
    //                    indoorLocationListener.onLocationInterrupt(NexdIndoorLocation.LocationState.LOCATION_INTERRUP_LOCATION_CONFIG_NONEXISTENT);
    //                    indoorLocation.setCurrentFloorId(-1L);
    //                    interrupt = true;
    //                    Log.e("", e.getMessage());
    //                }
    //            }
    //            return null;
    //        }
    //    }
    //
    //    // 检查 加载 切层配置文件
    //    private class DefaultDetectionConfigThread extends SimpleTask {
    //
    //        private long buildingId;
    //        private NexdIndoorLocationListener indoorLocationListener;
    //
    //        public DefaultDetectionConfigThread(long buildingId, NexdIndoorLocationListener indoorLocationListener) {
    //            this.buildingId = buildingId;
    //            this.indoorLocationListener = indoorLocationListener;
    //        }
    //
    //        @Override
    //        protected Object doInBackground() {
    //            if (indoorLocation.getCurrentBuildingId() == -1L || indoorLocation.getCurrentBuildingId() != buildingId) {
    //                //                Log.d("location_test", "需要加载切层文件");
    //                try {
    //                    indoorLocation.initDetectionConfig(NexdIndoorLocation.getConfigurationPath(buildingId).toString() + buildingId + ".CONF", NexdIndoorLocation.getConfigurationPath(buildingId).toString() + buildingId + ".model", NexdIndoorLocation.getConfigurationPath(buildingId).toString() + buildingId + ".wifilist");
    //                    indoorLocation.setCurrentBuildingId(buildingId);
    //                } catch (IOException e) {
    //                    indoorLocationListener.onLocationInterrupt(NexdIndoorLocation.LocationState.LOCATION_INTERRUP_LOCATION_CONFIG_NONEXISTENT);
    //                    indoorLocation.setCurrentBuildingId(-1L);
    //                    Log.e("", e.getMessage());
    //                }
    //            }
    //            return null;
    //        }
    //    }

    public void free() {
        indoorLocation.free();
    }
}
